#include <chrono>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <memory>
#include <sstream>
#include <thread>
#include <vector>
#include <stddef.h> /* size_t */
#include <iomanip>
#include <string>

#include <nlohmann/json.hpp>

#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>

#include "TxDNN/txdnn_graph.h"
#include "txdnn_bindings.h"
#include "pylogger.h"
#include "utils/logger/logger_internal.h"

#define LOG_TAG "txdnn.pytxdnn"

namespace py = pybind11;

namespace pytxdnn {

void bindTxdnn(py::module& txdnn) {
  // enum txdnnStatus_t in txdnn_graph.h
  py::enum_<txdnnStatus_t>(txdnn, "TxdnnStatus")
    .value("SUCCESS", txdnnStatus_t::TXDNN_STATUS_SUCCESS)
    .value("ERROR", txdnnStatus_t::TXDNN_STATUS_UNKNOWN)
    .value("PARAM1_ERROR", txdnnStatus_t::TXDNN_STATUS_BAD_PARAM)
    .value("PARAM2_ERROR", txdnnStatus_t::TXDNN_STATUS_BAD_PARAM_NULL_POINTER)
    .value("PARAM3_ERROR", txdnnStatus_t::TXDNN_STATUS_BAD_PARAM_MISALIGNED_POINTER)
    .value("EXECUTION_FAILED", txdnnStatus_t::TXDNN_STATUS_EXECUTION_FAILED)
    .value("EXECUTION_FAILED_TXDART", txdnnStatus_t::TXDNN_STATUS_EXECUTION_FAILED_TXDART)
    // .value("DEVICE_IN_IDLE", txdnnStatus_t::RET_DEVICE_IN_IDLE)
    // .value("DEVICE_IN_ATTACH", txdnnStatus_t::RET_DEVICE_IN_ATTACH)
    // .value("DEVICE_ATTACH_SUCCESS", txdnnStatus_t::RET_DEVICE_ATTACH_SUCCESS)
    // .value("DEVICE_ATTACH_READY", txdnnStatus_t::RET_DEVICE_ATTACH_READY)
    // .value("DEVICE_LOSE_CONNECT", txdnnStatus_t::RET_DEVICE_LOSE_CONNECT)
    // .value("ENV_CLEAN_UP", txdnnStatus_t::RET_ENV_CLEAN_UP)
    .export_values();


  py::enum_<txdnn::ILogger::Level>(txdnn, "LoggerLevel")
    .value("Emergent", txdnn::ILogger::Level::Emergent)
    .value("Alert", txdnn::ILogger::Level::Alert)
    .value("Critical", txdnn::ILogger::Level::Critical)
    .value("Error", txdnn::ILogger::Level::Error)
    .value("Warning", txdnn::ILogger::Level::Warning)
    .value("Notice", txdnn::ILogger::Level::Notice)
    .value("Info", txdnn::ILogger::Level::Info)
    .value("Debug", txdnn::ILogger::Level::Debug)
    .value("Verbose", txdnn::ILogger::Level::Verbose)
    .export_values();


  py::class_<DefaultLogger>(txdnn, "TxdnnLogger")
    .def(py::init<std::string, txdnn::ILogger::Level>(), py::arg("file_path") = "",
         py::arg("level") = txdnn::ILogger::Level::Warning)
    .def_readwrite("level", &DefaultLogger::level_);

} // void bindTxdnn(py::module& txdnn)

} // namespace pytxdnn
